package com.shop.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shop.admin.constant.AdminConstant;
import com.shop.admin.constant.IndentConstant;
import com.shop.admin.dao.AllOrderDao;
import com.shop.admin.dao.ShopIndentDao;
import com.shop.admin.dao.ShopOrderDao;
import com.shop.admin.dao.ShopStockDao;
import com.shop.admin.dto.DeliveryDTO;
import com.shop.admin.entity.*;
import com.shop.admin.orgvo.SchoolOrgAllOrderVo;
import com.shop.admin.orgvo.SchoolOrgGeneralReport;
import com.shop.admin.orgvo.SchoolOrgYearDataVo;
import com.shop.admin.orgvo.ThisOrderDataVo;
import com.shop.admin.service.*;
import com.shop.admin.utils.CollectorsUtils;
import com.shop.admin.utils.PageUtils;
import com.shop.admin.vo.*;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Service
public class ShopIndentServiceImpl extends ServiceImpl<ShopIndentDao, ShopIndent> implements ShopIndentService {


    @Autowired
    private ShopGoodsService goodsService;

    @Autowired
    private ShopOrderService orderService;


    @Autowired
    private ShopIndentService indentService;

    @Autowired
    private ShopIndentDao shopIndentDao;

    @Autowired
    private ShopStockDao  stockDao;

    @Autowired
    private ShopOrderDao orderDao;



    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ShopUserService userService;

    @Autowired
    private ShopAddressService addressService;

    @Autowired
    private ShopAdminService adminService;

    @Resource
    private AllOrderService allOrderService;

    @Resource
    private OrganizationService organizationService;

    @Resource
    private AllOrderDao allOrderDao;


    @SneakyThrows
    public PageUtils queryPage(Map<String, Object> params) {
        Page<IndentVo> page = new Page<>(Long.parseLong(params.get("page").toString()),Long.valueOf(params.get("limit").toString()) );
        CompletableFuture<Page<IndentVo>> resPageCompletableFuture = CompletableFuture.supplyAsync(() -> {
            Page<IndentVo> resPage = shopIndentDao.queryPage(page, params);
            return resPage;
        }, threadPoolExecutor);
        Page<IndentVo> resPage = resPageCompletableFuture.get();
        List<IndentVo> records = JSON.parseArray(JSON.toJSONString(resPage.getRecords()), IndentVo.class);
        List<IndentVo> collect = records.parallelStream().map(item -> {
            List<ShopGoods> shopGoodsList = goodsService.list(new QueryWrapper<ShopGoods>().lambda().select(ShopGoods::getOrderId, ShopGoods::getOrderNum).eq(ShopGoods::getIndentId, item.getIndentId()));
            List<Integer> orderIds = shopGoodsList.stream().map(ShopGoods::getOrderId).collect(Collectors.toList());
            List<ShopOrder> shopOrderList = orderService.list(new QueryWrapper<ShopOrder>().lambda().select(ShopOrder::getOrderId, ShopOrder::getPriceCost)
                    .in(ShopOrder::getOrderId,orderIds));
            List<BigDecimal> costCounts = shopGoodsList.parallelStream().map(goods -> {
                BigDecimal costCount = BigDecimal.ZERO;
                for (ShopOrder order : shopOrderList) {
                    if (order.getOrderId().equals(goods.getOrderId().longValue())) {
                        Integer orderNum = goods.getOrderNum();
                        BigDecimal PriceCost = new BigDecimal(orderNum).multiply(order.getPriceCost());
                        costCount = costCount.add(PriceCost);
                    }
                }
                return costCount;
            }).collect(Collectors.toList());
            BigDecimal reduce = costCounts.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setProfit(item.getPrices().subtract(reduce));
            List<GoodsVo> goodsVOList = item.getGoodsVOList();
            goodsVOList.parallelStream().map(goodsVO -> {
                Long orderId = goodsVO.getOrderId();
                ShopOrder shopOrder = orderService.selectById(orderId.intValue());
                goodsVO.setOrderName(shopOrder.getOrderName());
                goodsVO.setPriceDiscounts(shopOrder.getPriceDiscounts());
                goodsVO.setPurchasePrice(goodsVO.getPurchasePrice());
                return goodsVO;
            }).collect(Collectors.toList());
            return item;
        }).collect(Collectors.toList());
        resPage.setRecords(collect);
        PageUtils pageUtils = new PageUtils(resPage);
        return pageUtils;
    }

    @Override
    @Transactional
    //@CacheEvict(value = "dataCount",allEntries = true)
    public void updateStatus(IndentStatusVo vo) {
        ShopIndent shopIndent = new ShopIndent();
        if (vo.getIndentStatus()==0){
            shopIndent.setIndentStatus(IndentConstant.StatusEnum.CANCEL.getCode());
            shopIndent.setIndentId(vo.getIndentId());
            shopIndent.setUpdateTime(new Date());
            this.updateById(shopIndent);

            ShopIndent indent = indentService.getById(vo.getIndentId());
            List<ShopGoods> shopGoodsList = goodsService.list(new QueryWrapper<ShopGoods>().lambda().eq(ShopGoods::getIndentId, vo.getIndentId()));

            List<Integer> orderIds = shopGoodsList.stream().map(ShopGoods::getOrderId).collect(Collectors.toList());
            List<ShopOrder> shopOrderList = orderService.list(new QueryWrapper<ShopOrder>().lambda().select(ShopOrder::getOrderId, ShopOrder::getPriceCost)
                    .in(ShopOrder::getOrderId,orderIds));
            List<BigDecimal> costCounts = shopGoodsList.parallelStream().map(goods -> {
                BigDecimal costCount = BigDecimal.ZERO;
                for (ShopOrder order : shopOrderList) {
                    if (order.getOrderId().equals(goods.getOrderId().longValue())) {
                        Integer orderNum = goods.getOrderNum();
                        BigDecimal PriceCost = new BigDecimal(orderNum).multiply(order.getPriceCost());
                        costCount = costCount.add(PriceCost);
                    }
                }
                return costCount;
            }).collect(Collectors.toList());
            BigDecimal reduce = costCounts.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal indentProfit = indent.getPrices().subtract(reduce);

            stockDao.updateStockCount(shopGoodsList);
            AllOrder allOrder = new AllOrder();
            allOrder.setOrderStatus(vo.getIndentStatus());
            allOrderService.update(allOrder,new QueryWrapper<AllOrder>().lambda().eq(AllOrder::getOrderId,vo.getIndentId()));

            ShopIndent indentServiceById = indentService.getById(vo.getIndentId());
//            Organization organizationServiceById = organizationService.getById(indentServiceById.getOrgId());
//
//            Organization organization = new Organization();
//            organization.setId(indentServiceById.getOrgId());
//            if (!organizationServiceById.getCommission().equals(0)){//如果利润额不为0，则使用利润额算数
//                //回滚组织的余额
//                organization.setAccountMoney(organizationServiceById.getAccountMoney()//当前的组织余额-
//                        .subtract(indentProfit//当前的订单利润*
//                                .multiply(new BigDecimal(1)//1-微信费率
//                                .subtract(organizationServiceById.getWxRate()))
//                                .multiply(organizationServiceById.getCommission())));//*组织利润额度抽成
//
//                //回滚e键校园的收入总额
//                organization.setAccountIncome(organizationServiceById.getAccountIncome()//当前ejxy的收入总额-
//                        .subtract(indentProfit//当前的订单利润-
//                               .subtract(indentProfit//当前的订单利润*
//                                       .multiply(new BigDecimal(1)//1-微信费率
//                                               .subtract(organizationServiceById.getWxRate()))
//                                       .multiply(organizationServiceById.getCommission()))));//*组织利润额度抽成
//            }
//            else {//利润额为0，则进行销售额运算
//                organization.setAccountMoney(organizationServiceById.getAccountMoney()//当前的组织余额-
//                        .subtract(indent.getPrices()//当前的订单销售*
//                                .multiply(new BigDecimal(1)//1-微信费率
//                                        .subtract(organizationServiceById.getWxRate()))
//                                .multiply(organizationServiceById.getCommission())));//*组织销售额度抽成
//
//                //回滚e键校园的收入总额
//                organization.setAccountIncome(organizationServiceById.getAccountIncome()//当前ejxy的收入总额-
//                        .subtract(indentProfit//当前的订单利润-
//                                .subtract(indent.getPrices()//当前的订单销售*
//                                        .multiply(new BigDecimal(1)//1-微信费率
//                                                .subtract(organizationServiceById.getWxRate()))
//                                        .multiply(organizationServiceById.getCommission()))));//*组织销售额度抽成
//            }
//            organizationService.updateById(organization);
        }
        if (vo.getIndentStatus()==1){
            shopIndent.setIndentStatus(IndentConstant.StatusEnum.CIVET.getCode());
            shopIndent.setIndentId(vo.getIndentId());
            shopIndent.setUpdateTime(new Date());
            this.updateById(shopIndent);
            AllOrder allOrder = new AllOrder();
            allOrder.setOrderStatus(vo.getIndentStatus());
            allOrderService.update(allOrder,new QueryWrapper<AllOrder>().lambda().eq(AllOrder::getOrderId,vo.getIndentId()));
        }
        if (vo.getIndentStatus()==2){
            shopIndent.setIndentStatus(IndentConstant.StatusEnum.ASSIGNED.getCode());
            shopIndent.setIndentId(vo.getIndentId());
            shopIndent.setUpdateTime(new Date());
            this.updateById(shopIndent);
            AllOrder allOrder = new AllOrder();
            allOrder.setOrderStatus(vo.getIndentStatus());
            allOrderService.update(allOrder,new QueryWrapper<AllOrder>().lambda().eq(AllOrder::getOrderId,vo.getIndentId()));
        }
        if (vo.getIndentStatus()==3){
            shopIndent.setIndentStatus(IndentConstant.StatusEnum.FINISH.getCode());
            shopIndent.setIndentId(vo.getIndentId());
            shopIndent.setUpdateTime(new Date());
            this.updateById(shopIndent);
            ShopIndent indent = indentService.getById(vo.getIndentId());
            List<ShopGoods> shopGoodsList = goodsService.list(new QueryWrapper<ShopGoods>().lambda().eq(ShopGoods::getIndentId, vo.getIndentId()));
            List<Integer> orderIds = shopGoodsList.stream().map(ShopGoods::getOrderId).collect(Collectors.toList());
            List<ShopOrder> shopOrderList = orderService.list(new QueryWrapper<ShopOrder>().lambda().select(ShopOrder::getOrderId, ShopOrder::getPriceCost)
                    .in(ShopOrder::getOrderId,orderIds));
            List<BigDecimal> costCounts = shopGoodsList.parallelStream().map(goods -> {
                BigDecimal costCount = BigDecimal.ZERO;
                for (ShopOrder order : shopOrderList) {
                    if (order.getOrderId().equals(goods.getOrderId().longValue())) {
                        Integer orderNum = goods.getOrderNum();
                        BigDecimal PriceCost = new BigDecimal(orderNum).multiply(order.getPriceCost());
                        costCount = costCount.add(PriceCost);
                    }
                }
                return costCount;
            }).collect(Collectors.toList());
            BigDecimal reduce = costCounts.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal indentProfit = indent.getPrices().subtract(reduce);
            orderDao.updateSaleCount(shopGoodsList);
            AllOrder allOrder = new AllOrder();
            allOrder.setOrderStatus(vo.getIndentStatus());
            allOrderService.update(allOrder,new QueryWrapper<AllOrder>().lambda().eq(AllOrder::getOrderId,vo.getIndentId()));

            ShopIndent indentServiceById = indentService.getById(vo.getIndentId());
            Organization organizationServiceById = organizationService.getById(indentServiceById.getOrgId());
            Organization organization = new Organization();
            organization.setId(indentServiceById.getOrgId());
//            organization.setSalesCommission(organizationServiceById.getSalesCommission().add(indentServiceById.getPrices()));
//            organization.setAccountMoney(organizationServiceById.getAccountMoney().add(indentProfit.multiply(new BigDecimal(1).subtract(organizationServiceById.getWxRate())).multiply(organizationServiceById.getCommission())));
            if (organizationServiceById.getCommission().compareTo(BigDecimal.ZERO)!=0){//如果利润额不为0，则使用利润额算数
                //叠加组织的余额
                organization.setAccountMoney(organizationServiceById.getAccountMoney()//当前的组织余额-
                        .add(indentProfit//当前的订单利润*
                                .multiply(new BigDecimal(1)//1-微信费率
                                        .subtract(organizationServiceById.getWxRate()))
                                .multiply(organizationServiceById.getCommission())));//*组织利润额度抽成

                //叠加键校园的收入总额
                organization.setAccountIncome(organizationServiceById.getAccountIncome()//当前ejxy的收入总额+
                        .add(indentProfit//当前的订单利润-
                                .subtract(indentProfit//当前的订单利润*
                                        .multiply(new BigDecimal(1)//1-微信费率
                                                .subtract(organizationServiceById.getWxRate()))
                                        .multiply(organizationServiceById.getCommission())))
                        .subtract(indent.getPrices().multiply(organizationServiceById.getWxRate()))
                );//*组织利润额度抽成
            }
            else {//利润额为0，则进行销售额运算
                organization.setAccountMoney(organizationServiceById.getAccountMoney()//当前的组织余额+
                        .add(indent.getPrices()//当前的订单销售*
                                .multiply(new BigDecimal(1)//1-微信费率
                                        .subtract(organizationServiceById.getWxRate()))
                                .multiply(organizationServiceById.getSalesCommission())));//*组织销售额度抽成

                //e键校园的收入总额
                organization.setAccountIncome(organizationServiceById.getAccountIncome()//当前ejxy的收入总额+
                        .add(indent.getPrices()//当前的订单销售-
                                .subtract(indent.getPrices()//当前的订单销售*
                                        .multiply(new BigDecimal(1)//1-微信费率
                                                .subtract(organizationServiceById.getWxRate()))
                                        .multiply(organizationServiceById.getSalesCommission())))//*组织销售额度抽成
                        .subtract(indent.getPrices().multiply(organizationServiceById.getWxRate()))
                );
            }
            organizationService.updateById(organization);
        }

    }

    @Override
    public DataVo queryPageData(Map<String, Object> params) {
        CompletableFuture<DataVo> dataFuture = CompletableFuture.supplyAsync(() -> shopIndentDao.getDataCount(params) ,threadPoolExecutor);
        CompletableFuture<Integer> countFuture = CompletableFuture.supplyAsync(() -> userService.count()  ,threadPoolExecutor);
        CompletableFuture<Integer> numFuture = CompletableFuture.supplyAsync(() -> shopIndentDao.efficaciousUserNum() ,threadPoolExecutor);
        CompletableFuture.allOf(dataFuture,countFuture,numFuture).join();
        DataVo dataVo = dataFuture.join();
        dataVo.setNum(Long.valueOf( countFuture.join() ));
        dataVo.setUserCount( numFuture.join() );
        return dataVo;
    }

    @Override
    public Map<String, List<Object>> getImageIzation(Map<String, Object> params) {
        List<IzationVo> datas = this.baseMapper.getDataIzation(params);
        List<Object> days = datas.stream().map(IzationVo::getDate).collect(Collectors.toList());
        List<Object> decimals = datas.stream().map(IzationVo::getTotal).collect(Collectors.toList());
        List<Object> profit = datas.stream().map(IzationVo::getProfit).collect(Collectors.toList());
        List<Object> counts = datas.stream().map(IzationVo::getStrokeCount).collect(Collectors.toList());
        Map<String, List<Object>> map=new HashMap<>();
        map.put("日期",days);
        map.put("销售额",decimals);
        map.put("利润额",profit);
        map.put("销售量",counts);
        return map;
    }

    @Override
    @Transactional
    public int deleteByXss(Map<String, Object> params) {
        QueryWrapper<ShopIndent> queryWrapper = new QueryWrapper<>();
        String key=(String) params.get("key");
        if(key!=null){
            queryWrapper.lambda().select(ShopIndent::getIndentId,ShopIndent::getUserId,ShopIndent::getRemark).eq(ShopIndent::getUserId,key)
                .or().like(ShopIndent::getRemark,key);
        }
        List<ShopIndent> shopIndents = this.list(queryWrapper);

        List<Long> indentIds = shopIndents.stream().map(ShopIndent::getIndentId).collect(Collectors.toList());
        int f=0;
        if (indentIds.size()!=0){
            this.baseMapper.delete(new QueryWrapper<ShopIndent>().lambda().in(ShopIndent::getIndentId,indentIds));
            f=goodsService.deleteXss(indentIds);
        }
        return f;
    }

    @Override
    public void saveOrUpdateAdmin(DeliveryDTO dto) {
        ShopIndent shopIndent = new ShopIndent();
        BeanUtils.copyProperties(dto,shopIndent);
        shopIndent.setUpdateTime(new Date());
        this.updateById(shopIndent);
    }

    @Override
    public List<AdminCountVo> getAdminCount(Map<String, Object> params) {
        Integer twoCount = getCount(AdminConstant.AdminEnum.TWO.getCode());
        Integer threeCount = getCount(AdminConstant.AdminEnum.THREE.getCode());
        Integer fourCount = getCount(AdminConstant.AdminEnum.FOUR.getCode());
        Integer fiveCount = getCount(AdminConstant.AdminEnum.FIVE.getCode());
        Integer twoDay = getDay(AdminConstant.AdminEnum.TWO.getCode());
        Integer threeDay = getDay(AdminConstant.AdminEnum.THREE.getCode());
        Integer fourDay = getDay(AdminConstant.AdminEnum.FOUR.getCode());
        Integer fiveDay = getDay(AdminConstant.AdminEnum.FIVE.getCode());
        Integer twoYesterDay = getYesterDay(AdminConstant.AdminEnum.TWO.getCode());
        Integer threeYesterDay = getYesterDay(AdminConstant.AdminEnum.THREE.getCode());
        Integer fourYesterDay = getYesterDay(AdminConstant.AdminEnum.FOUR.getCode());
        Integer fiveYesterDay = getYesterDay(AdminConstant.AdminEnum.FIVE.getCode());
        AdminCountVo.CountVo two = setCount(twoDay, twoCount,twoYesterDay);
        AdminCountVo.CountVo three = setCount(threeDay, threeCount,threeYesterDay);
        AdminCountVo.CountVo four = setCount(fourDay, fourCount,fourYesterDay);
        AdminCountVo.CountVo five = setCount(fiveDay, fiveCount,fiveYesterDay);
        AdminCountVo twoAdmin = setAdmin(AdminConstant.AdminEnum.TWO.getCode(), two);
        AdminCountVo threeAdmin = setAdmin(AdminConstant.AdminEnum.THREE.getCode(), three);
        AdminCountVo fourAdmin = setAdmin(AdminConstant.AdminEnum.FOUR.getCode(), four);
        AdminCountVo fiveAdmin = setAdmin(AdminConstant.AdminEnum.FIVE.getCode(), five);
        List<AdminCountVo> adminCountVOS=new ArrayList<>();
        adminCountVOS.add(twoAdmin);
        adminCountVOS.add(threeAdmin);
        adminCountVOS.add(fourAdmin);
        adminCountVOS.add(fiveAdmin);
        return adminCountVOS;
    }

    @Override
    @SneakyThrows
    public List<UserRankingVo> userRanking(Map<String, Object> params) {
        QueryWrapper<ShopIndent> queryWrapper=new QueryWrapper<>();

        String type= (String) params.get("type");
        if(type.equals("Yesterday")){
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DATE,-1);
            Date time = calendar.getTime();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(time);
            queryWrapper.lambda().like(ShopIndent::getCreateTime,format);
        }

        if(type.equals("Today")){
            String now = LocalDate.now().toString();
            queryWrapper.lambda().like(ShopIndent::getCreateTime,now);
        }

        if(type.equals("Count")){

        }

        List<ShopIndent> shopIndentsDatabaseAll = this.list(queryWrapper.lambda().eq(ShopIndent::getIndentStatus,3));
        if (CollectionUtils.isEmpty(shopIndentsDatabaseAll)) {
            return Collections.emptyList();
        }
        Map<Integer, BigDecimal> integerBigDecimalMap = shopIndentsDatabaseAll.stream()
                .collect(Collectors.groupingBy(ShopIndent::getUserId, CollectorsUtils.summingBigDecimal(ShopIndent::getPrices)));
        Map<Integer, Long> userIndentCount= shopIndentsDatabaseAll.stream()
                .collect(Collectors.groupingBy(ShopIndent::getUserId, Collectors.counting()));
        Map<Integer, BigDecimal> sortedMap = new LinkedHashMap<>();
        integerBigDecimalMap.entrySet().stream()
                .sorted(Map.Entry.<Integer,BigDecimal> comparingByValue().reversed()).limit(10)
                .forEachOrdered(e -> sortedMap.put(e.getKey(),e.getValue()));
        List<Integer> sortedMapKeyList = new ArrayList<Integer>(sortedMap.keySet());
        CompletableFuture<List<User>> userListCompletableFuture = CompletableFuture.supplyAsync(() -> {
            List<User> userList = userService.list(new QueryWrapper<User>().lambda().
                    select(User::getUserId, User::getUserName, User::getUserNick, User::getPhonenumber).in(User::getUserId, sortedMapKeyList));
            if (CollectionUtils.isEmpty(userList)) {
                return Collections.emptyList();
            }
            return userList;
        }, threadPoolExecutor);
        List<User> userList = userListCompletableFuture.get();
        List<Long> longs = userList.stream().map(i -> i.getUserId()).collect(Collectors.toList());
        List<ShopAddress> shopAddresses = addressService.list(new QueryWrapper<ShopAddress>().lambda().in(ShopAddress::getUserId, longs));
        List<UserRankingVo> userRankingVos = sortedMapKeyList.parallelStream().map(vo -> {
            UserRankingVo userRankingVo = new UserRankingVo();
            userList.forEach(user -> {
                if (vo.equals(user.getUserId().intValue())) {
                    userRankingVo.setUserId(user.getUserId().intValue()).setUserNameCount(user.getUserName() + "/" + user.getUserNick()).setPhoneNumber(user.getPhonenumber());
                }
            });
            sortedMapKeyList.forEach(key -> {
                if (vo.equals(key)) {
                    userRankingVo.setUserIndentAmountCount(sortedMap.get(key)).setIndentNum(userIndentCount.get(key));
                }
            });
            shopAddresses.forEach(address ->{
                if (vo.equals(address.getUserId().intValue())){
                    userRankingVo.setUserAddress(address.getDetailedAddress());
                }
            });
            return userRankingVo;
        }).collect(Collectors.toList());
        return userRankingVos;
    }

    @Override
    public PageUtils schoolOrgGeneralReport(Map<String, Object> params) {
        Long pageValue = params.get("page") == null ? 1L : Long.parseLong(params.get("page").toString());
        Long limitValue = params.get("limit") == null ? 0L : Long.parseLong(params.get("limit").toString());
        List<Integer> orgId = organizationService.list(new LambdaQueryWrapper<Organization>()
                .eq(Organization::getFatherId, Integer.parseInt(params.get("orgId").toString())))
                .stream()
                .map(Organization::getId)
                .collect(Collectors.toList());
        if (orgId.size()== 0 ) return new PageUtils(null,0);
        Page<SchoolOrgGeneralReport> page = new Page<>(pageValue, limitValue);
        Page<SchoolOrgAllOrderVo> allOrderPage = new Page<>(pageValue, limitValue);

        Page<SchoolOrgGeneralReport> res = shopIndentDao.schoolOrgGeneralReportPage(page,orgId);
        Page<SchoolOrgAllOrderVo>  allOrderRes = allOrderDao.schoolOrgGeneralReportRunningPage(allOrderPage,Integer.parseInt(params.get("orgId").toString()));
        Map<String, SchoolOrgAllOrderVo> allOrderVoMap = allOrderRes.getRecords().stream()
                .collect(Collectors.toMap(SchoolOrgAllOrderVo::getMonth, vo -> vo));

        List<SchoolOrgGeneralReport> mergedReports = res.getRecords().stream()
                .map(report -> {
                    SchoolOrgAllOrderVo matchingOrderVo = allOrderVoMap.get(report.getMonth());
                    if (matchingOrderVo != null) {
                        report.setRunningSaleCount(matchingOrderVo.getRunningSaleCount());
                        report.setRunningPricesCount(matchingOrderVo.getRunningPricesCount());
                        report.setRunningProfits(matchingOrderVo.getRunningProfits());
                        report.setMonthlySales(report.getSnacksPricesCount().add(matchingOrderVo.getRunningPricesCount()));
                        report.setMonthlyProfit(report.getSnacksProfits().add(matchingOrderVo.getRunningProfits()));
                    } else {
                        report.setRunningSaleCount(0);
                        report.setRunningPricesCount(BigDecimal.ZERO);
                        report.setRunningProfits(BigDecimal.ZERO);
                        report.setMonthlySales(BigDecimal.ZERO);
                        report.setMonthlyProfit(BigDecimal.ZERO);
                    }
                    return report;
                })
                .collect(Collectors.toList());

        List<SchoolOrgGeneralReport> schoolOrgGeneralReports = mergedReports.parallelStream().map(i -> {
                SchoolOrgGeneralReport schoolOrgGeneralReport = new SchoolOrgGeneralReport();
                BeanUtils.copyProperties(i, schoolOrgGeneralReport);
                schoolOrgGeneralReport.setMonthlySales(i.getSnacksPricesCount().add(i.getRunningPricesCount()));
                schoolOrgGeneralReport.setMonthlyProfit(i.getSnacksProfits().add(i.getRunningProfits()));
                return schoolOrgGeneralReport;
            }).collect(Collectors.toList());

        List<SchoolOrgGeneralReport> completedReports = new ArrayList<>();

        String prevMonth = schoolOrgGeneralReports.get(0).getMonth();
        completedReports.add(schoolOrgGeneralReports.get(0));

        for (int i = 1; i < schoolOrgGeneralReports.size(); i++) {
            String currentMonth = schoolOrgGeneralReports.get(i).getMonth();
            int diff = getMonthDifference(prevMonth, currentMonth);
            if (diff > 1) {
                for (int j = 1; j < diff; j++) {
                    String missingMonth = getNextMonth(prevMonth);
                    completedReports.add(new SchoolOrgGeneralReport(missingMonth, BigDecimal.ZERO, BigDecimal.ZERO, 0, 0, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO));
                    prevMonth = missingMonth;
                }
            }
            completedReports.add(schoolOrgGeneralReports.get(i));
            prevMonth = currentMonth;
        }

        for (int i = 0; i < completedReports.size(); i++) {
            SchoolOrgGeneralReport currentReport = completedReports.get(i);

            if (i > 0) {
                SchoolOrgGeneralReport previousReport = completedReports.get(i - 1);
                BigDecimal currentMonthlySales =currentReport.getMonthlySales();
                BigDecimal currentMonthlyProfit =currentReport.getMonthlyProfit();
                BigDecimal previousMonthlySales =previousReport.getMonthlySales();
                BigDecimal previousMonthlyProfit =previousReport.getMonthlyProfit();

                BigDecimal monthlySalesProportion;
                BigDecimal monthlyProfitProportion;

                if (previousMonthlySales.compareTo(BigDecimal.ZERO) == 0) {
                    // 如果上一条的 monthlySales 为零，将当前的 monthlySalesProportion 设置为 1
                    monthlySalesProportion = BigDecimal.ONE;
                } else {
                    // 计算当前的 monthlySalesProportion
                    monthlySalesProportion = currentMonthlySales.divide(previousMonthlySales, 4, RoundingMode.HALF_UP)
                            .subtract(BigDecimal.ONE);
                }

                if (previousMonthlyProfit.compareTo(BigDecimal.ZERO) == 0) {
                    // 如果上一条的 monthlyProfit 为零，将当前的 monthlyProfitProportion 设置为 1
                    monthlyProfitProportion = BigDecimal.ONE;
                } else {
                    // 计算当前的 monthlyProfitProportion
                    monthlyProfitProportion = currentMonthlyProfit.divide(previousMonthlyProfit, 4, RoundingMode.HALF_UP)
                            .subtract(BigDecimal.ONE);
                }

                currentReport.setMonthlySalesProportion(monthlySalesProportion.setScale(2, RoundingMode.HALF_UP));
                currentReport.setMonthlyProfitProportion(monthlyProfitProportion.setScale(2, RoundingMode.HALF_UP));
            } else {
                // 对于第一条数据，将 monthlySalesProportion 和 monthlyProfitProportion 设置为 0
                currentReport.setMonthlySalesProportion(BigDecimal.ZERO);
                currentReport.setMonthlyProfitProportion(BigDecimal.ZERO);
            }

            if (currentReport.getMonthlySales().compareTo(BigDecimal.ZERO) == 0) {
                // 如果当前的 monthlySales 为零，将下一条的 monthlySalesProportion 设置为 1
                if (i + 1 < completedReports.size()) {
                    completedReports.get(i + 1).setMonthlySalesProportion(BigDecimal.ONE);
                }
            }

            if (currentReport.getMonthlyProfit().compareTo(BigDecimal.ZERO) == 0) {
                // 如果当前的 monthlyProfit 为零，将下一条的 monthlyProfitProportion 设置为 1
                if (i + 1 < completedReports.size()) {
                    completedReports.get(i + 1).setMonthlyProfitProportion(BigDecimal.ONE);
                }
            }
        }

        int pageSize = (int) res.getSize(); // 每页记录数
        int pageNum = (int) res.getCurrent(); // 当前页码
        int totalRecords = completedReports.size(); // 总记录数
        int startIndex = (pageNum - 1) * pageSize; // 起始索引
        int endIndex = Math.min(startIndex + pageSize, totalRecords);
        List<SchoolOrgGeneralReport> updatedRecords = completedReports.subList(startIndex, endIndex);
        res.setRecords(updatedRecords);
        return new PageUtils(res);
    }

    @Override
    public List<SchoolOrgYearDataVo> schoolOrgYearProportion(Map<String, Object> params) {
        List<Integer> orgId = organizationService.list(new LambdaQueryWrapper<Organization>()
                .eq(Organization::getFatherId, Integer.parseInt(params.get("orgId").toString())))
                .stream()
                .map(Organization::getId)
                .collect(Collectors.toList());
        ThisOrderDataVo thisYearDataSnacks = shopIndentDao.getThisYearOrderDataSnacks(orgId);//今年零食销售额，利润额，数量
        ThisOrderDataVo lastYearDataSnacks = shopIndentDao.getLastYearOrderDataSnacks(orgId);//去年零食销售额，利润额，数量
        ThisOrderDataVo thisYearDataRunning = allOrderDao.getThisYearOrderDataRunningErrands(params);//今年跑腿销售额，利润额，数量
        ThisOrderDataVo lastYearDataRunning = allOrderDao.getLastYearOrderDataRunningErrands(params);//去年跑腿销售额，利润额，数量
        ArrayList<SchoolOrgYearDataVo> schoolOrgYearDataVo = new ArrayList<>();
        schoolOrgYearDataVo
                .add(new SchoolOrgYearDataVo(thisYearDataSnacks.getSalesThisYear()
                .add(lastYearDataSnacks.getLastYearSales())
                .add(thisYearDataRunning.getSalesThisYear())
                .add(lastYearDataRunning.getLastYearSales())
                ,thisYearDataSnacks.getProfitThisYear()
                .add(lastYearDataSnacks.getLastYearProfit())
                .add(thisYearDataRunning.getProfitThisYear()
                .add(lastYearDataRunning.getLastYearProfit()))
                ,thisYearDataSnacks.getNumCount()+lastYearDataSnacks.getNumCount()+thisYearDataRunning.getNumCount()+lastYearDataRunning.getNumCount()
                ,thisYearDataSnacks.getSalesThisYear().add(thisYearDataRunning.getSalesThisYear())
                ,thisYearDataSnacks.getProfitThisYear().add(thisYearDataRunning.getProfitThisYear())
                ,thisYearDataSnacks.getNumCount()+thisYearDataRunning.getNumCount()
                ,lastYearDataSnacks.getLastYearSales().add(lastYearDataRunning.getLastYearSales())
                ,lastYearDataSnacks.getLastYearProfit().add(lastYearDataRunning.getLastYearProfit())
                ,lastYearDataSnacks.getNumCount()+lastYearDataRunning.getNumCount()
                ,(thisYearDataSnacks.getSalesThisYear().add(thisYearDataRunning.getSalesThisYear())).divide(lastYearDataSnacks.getLastYearSales().add(lastYearDataRunning.getLastYearSales()),RoundingMode.HALF_UP).subtract(new BigDecimal(1))
                ,(thisYearDataSnacks.getProfitThisYear().add(thisYearDataRunning.getProfitThisYear())).divide(lastYearDataSnacks.getLastYearProfit().add(lastYearDataRunning.getLastYearProfit()),RoundingMode.HALF_UP).subtract(new BigDecimal(1))));
        return schoolOrgYearDataVo;
    }

    public static int getMonthDifference(String startMonth, String endMonth) {
        String[] start = startMonth.split("-");
        String[] end = endMonth.split("-");
        int startYear = Integer.parseInt(start[0]);
        int startMonthValue = Integer.parseInt(start[1]);
        int endYear = Integer.parseInt(end[0]);
        int endMonthValue = Integer.parseInt(end[1]);

        return (endYear - startYear) * 12 + (endMonthValue - startMonthValue);
    }

    public static String getNextMonth(String month) {
        String[] parts = month.split("-");
        int year = Integer.parseInt(parts[0]);
        int monthValue = Integer.parseInt(parts[1]);

        if (monthValue == 12) {
            year++;
            monthValue = 1;
        } else {
            monthValue++;
        }
        return year + "-" + String.format("%02d", monthValue);
    }

    public Integer getCount(Integer id){
        QueryWrapper<ShopIndent> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(ShopIndent::getIndentStatus,3).eq(ShopIndent::getAdminId,id);
        Integer selectCount = this.baseMapper.selectCount(queryWrapper);
        return selectCount;
    }
    public Integer getDay(Integer id){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date(System.currentTimeMillis());
        String format = simpleDateFormat.format(date);
        QueryWrapper<ShopIndent> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(ShopIndent::getIndentStatus,3).eq(ShopIndent::getAdminId,id)
                .like(ShopIndent::getCreateTime,format);
        Integer selectCount = this.baseMapper.selectCount(queryWrapper);
        return selectCount;
    }
    public Integer getYesterDay(Integer id){
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,-1);
        Date time = calendar.getTime();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(time);
        QueryWrapper<ShopIndent> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(ShopIndent::getIndentStatus,3).eq(ShopIndent::getAdminId,id)
                .like(ShopIndent::getCreateTime,format);
        Integer selectCount = this.baseMapper.selectCount(queryWrapper);
        return selectCount;
    }

    public AdminCountVo.CountVo setCount(Integer day, Integer count, Integer yesterDay){
        AdminCountVo.CountVo countVO = new AdminCountVo.CountVo();
        countVO.setNumDay(day);
        countVO.setNumCount(count);
        countVO.setNumYesterDay(yesterDay);
        return countVO;
    }
    public AdminCountVo setAdmin(Integer id, AdminCountVo.CountVo count){
        AdminCountVo adminCountVO = new AdminCountVo();
        adminCountVO.setId(id);
        String adminName = adminService.getById(id).getAdminName();
        Integer receiveEmail = adminService.getById(id).getReceiveEmail();
        adminCountVO.setReceiveEmail(receiveEmail);
        adminCountVO.setAdminName(adminName);
        adminCountVO.setCountVOS(count);
        return adminCountVO;
    }
}